﻿#include<iostream>
#include<afxwin.h>
#include<ctime>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<math.h>
#include <thread>
#include "ini.h"
#include "gs-public.h"
#include "gs-opencv.h"
#include "gs-mfc.h"
#include "Ciclequeue.h"
#pragma comment(lib, "opencv_core460.lib")
#pragma comment(lib, "opencv_imgproc460.lib")
#pragma comment(lib, "opencv_imgcodecs460.lib")
#pragma comment(lib, "opencv_highgui460.lib")
using namespace std;
using namespace cv;

#define KEY_PRESSED(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x0001) ? 1:0) //如果为真，表示按下过
#define KEY_PRESSING(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //如果为真，表示正处于按下状态

struct g_params {
	HWND hwnd;
	RECT rect;
	int width;
	int height;
	int dLR;
	int dTop;
	int dBottom;
	double rate;
	bool pause;
	RECT rect_center;
	RECT rect_blue;
	RECT rect_red;
	RECT rect_gb;
	Mat tpl_center;
	Mat tpl_point;
	Mat tpl_gb;
	Mat tpl_gb_new;
	long long time_fish;
	Ciclequeue* cq_blue;
	Ciclequeue* cq_red;
	int cqBlueSize;
	int cqRedSize;
	bool needFinish;
	bool existBar;
	int fishCount;
	bool systemPause;
	bool start;
	g_point point_fish;
};

struct g_config {
	int delays;
	int s_delays;
	int delays_finish_before;
	int delays_esc_before;
	int delays_esc_after;
	bool is_log;
	bool is_pause;
	bool is_auto;
	int throw_method;
	int throw_btn;
	string throw_btn_name;
	bool debug;
	bool debug_pic;
	float rate_center_x1;
	float rate_center_y1;
	float rate_center_x2;
	float rate_center_y2;
	float rate_blue_x1;
	float rate_blue_y1;
	float rate_red_x1;
	float rate_red_y1;
	float rate_gb_x1;
	float rate_gb_y1;
	float rate_gb_x2;
	float rate_gb_y2;
	float rate_fish_x;
	float rate_fish_y;
	friend std::ostream& operator <<(std::ostream& os, g_config const& a) {
		return os << '\n'
			<< "delays_finish_before\t= " << a.delays_finish_before << '\n'
			<< "delays_esc_before\t= " << a.delays_esc_before << '\n'
			<< "delays_esc_after\t= " << a.delays_esc_after << '\n'
			<< "is_pause  \t\t= " << a.is_pause << '\n'
			<< "is_auto  \t\t= " << a.is_auto << '\n'
			<< "throw_method\t\t= " << a.throw_method << '\n'
			<< "throw_btn\t\t= " << a.throw_btn_name << '\n'
			;
	}
};

// 程序全局变量
g_params params;

// 配置参数
g_config config;

// 读取配置文件
void loadConfig() {
	ZIni ini("config.ini");
	config.delays = ini.getInt("common", "delays", 60);
	config.s_delays = ini.getInt("common", "s_delays", 10);
	config.delays_finish_before = ini.getInt("common", "delays_finish_before", 2000);
	config.delays_esc_before = ini.getInt("common", "delays_esc_before", 1000);
	config.delays_esc_after = ini.getInt("common", "delays_esc_after", 1500);
	config.is_log = ini.getInt("common", "is_log", 0);
	config.is_pause = ini.getInt("common", "is_pause", 1);
	config.is_auto = ini.getInt("common", "is_auto", 1);
	// 抛竿方式：1键盘，2鼠标（默认1）
	config.throw_method = ini.getInt("common", "throw_method", 1);
	config.throw_btn_name = ini.get("common", "throw_btn", "1");
	config.throw_btn = getKeyVal(config.throw_btn_name);
	config.debug = ini.getInt("common", "debug", 0);
	config.debug_pic = ini.getInt("common", "debug_pic", 0);
	// 体力条位置比例(16:9)
	config.rate_center_x1 = ini.getFloat("common", "rate_center_x1", 0.351); // 450
	config.rate_center_y1 = ini.getFloat("common", "rate_center_y1", 0.0705); // 51
	config.rate_center_x2 = ini.getFloat("common", "rate_center_x2", 0.663); // 848
	config.rate_center_y2 = ini.getFloat("common", "rate_center_y2", 0.0835); // 60
	// 蓝色进度条位置比例(16:9)
	config.rate_blue_x1 = ini.getFloat("common", "rate_blue_x1", 0.328); // 420
	config.rate_blue_y1 = ini.getFloat("common", "rate_blue_y1", 0.105); // 76
	// 红色进度条位置比例(16:9)
	config.rate_red_x1 = ini.getFloat("common", "rate_red_x1", 0.668); // 856
	config.rate_red_y1 = ini.getFloat("common", "rate_red_y1", 0.104);  // 75
	// 关闭位置比例(16:9)
	config.rate_gb_x1 = ini.getFloat("common", "rate_gb_x1", 0.534); // 684
	config.rate_gb_y1 = ini.getFloat("common", "rate_gb_y1", 0.889); // 641
	config.rate_gb_x2 = ini.getFloat("common", "rate_gb_x2", 0.575); // 736
	config.rate_gb_y2 = ini.getFloat("common", "rate_gb_y2", 0.921); // 663
	// 收杆按钮位置比例(16:9)
	config.rate_fish_x = ini.getFloat("common", "rate_fish_x", 885); // 1133
	config.rate_fish_y = ini.getFloat("common", "rate_fish_y", 837); // 603
	std::cout << "已加载配置：" << config << endl;
}

// 获取体力条目标区域
RECT getCenterRect() {
	RECT res{};
	RECT s = params.rect;
	res.left = ceil(s.left + params.width * config.rate_center_x1);
	res.top = ceil(s.top + params.height * config.rate_center_y1);
	res.right = floor(s.left + params.width * config.rate_center_x2);
	res.bottom = floor(s.top + params.height * config.rate_center_y2);
	return res;
}

// 获取蓝色进度条目标区域
RECT getBlueRect() {
	RECT res{};
	RECT s = params.rect;
	res.left = ceil(s.left + params.width * config.rate_blue_x1);
	res.top = ceil(s.top + params.height * config.rate_blue_y1);
	res.right = res.left + 2;
	res.bottom = res.top + 2;
	return res;
}

// 获取红色进度条目标区域
RECT getRedRect() {
	RECT res{};
	RECT s = params.rect;
	res.left = ceil(s.left + params.width * config.rate_red_x1);
	res.top = ceil(s.top + params.height * config.rate_red_y1);
	res.right = res.left + 2;
	res.bottom = res.top + 2;
	return res;
}

// 获取关闭目标区域
RECT getGbRect() {
	RECT res{};
	RECT s = params.rect;
	res.left = ceil(s.left + params.width * config.rate_gb_x1);
	res.top = ceil(s.top + params.height * config.rate_gb_y1);
	res.right = floor(s.left + params.width * config.rate_gb_x2);
	res.bottom = floor(s.top + params.height * config.rate_gb_y2);
	return res;
}

// 获取收杆按钮区域
POINT getFishPoint() {
	POINT res{};
	RECT s = params.rect;
	res.x = ceil(s.left + params.width * config.rate_fish_x);
	res.y = ceil(s.top + params.height * config.rate_fish_y);
	return res;
}

// 是否正在向左、右走的标志
bool isL, isR;
// 停下
void keyStop() {
	if (isL) PostMessage(params.hwnd, WM_KEYUP, 'A', 0);
	if (isR) PostMessage(params.hwnd, WM_KEYUP, 'D', 0);
	isL = false;
	isR = false;
}
// 向左走
void keyLeft() {
	keyStop();
	PostMessage(params.hwnd, WM_KEYDOWN, 'A', 0);
	isL = true;
}
// 向右走
void keyRight() {
	keyStop();
	PostMessage(params.hwnd, WM_KEYDOWN, 'D', 0);
	isR = true;
}
// 向左走小步
void keyLeftS() {
	keyStop();
	PostMessage(params.hwnd, WM_KEYDOWN, 'A', 0);
	Sleep(config.s_delays);
	PostMessage(params.hwnd, WM_KEYUP, 'A', 0);
}
// 向右走小步
void keyRightS() {
	keyStop();
	PostMessage(params.hwnd, WM_KEYDOWN, 'D', 0);
	Sleep(config.s_delays);
	PostMessage(params.hwnd, WM_KEYUP, 'D', 0);
}
// 重置移动状态
void keyReset() {
	PostMessage(params.hwnd, WM_KEYUP, 'A', 0);
	PostMessage(params.hwnd, WM_KEYUP, 'D', 0);
	isL = false;
	isR = false;
}

// 获取模板
Mat getTpl(String name, int w, int h) {
	Mat src = imread("Resource\\" + name);//载入模版图像
	Mat res;
	resize(src, res, cv::Size(w, h)); // 缩小操作
	return res;
}
// 获取模板
Mat getTpl(String name) {
	Mat src = imread("Resource\\" + name);//载入模版图像
	return src;
}

// 读取进度条状态
void readStatusThread() {
	bool debug = config.debug;
	Ciclequeue* cq_blue = params.cq_blue;
	Ciclequeue* cq_red = params.cq_red;
	while (true) {
		// 暂停判断
		while (params.pause || params.systemPause) {
			Sleep(1000);
		}
		// 截取目标区域
		RECT rect_blue = params.rect_blue, rect_red = params.rect_red;
		Mat mat_blue = getSrc(rect_blue), mat_red = getSrc(rect_red);
		int blueTrueCount = 0, blueFalseCount = 0, redTrueCount = 0, redFalseCount = 0, blueTotal = 0, redTotal = 0;
		// 判断蓝色进度条
		for (int i = 0; i < mat_blue.rows; i++) {
			for (int j = 0; j < mat_blue.cols; j++) {
				int val = (int)mat_blue.at<uchar>(i, j);
				if (val == 73) {
					blueFalseCount++;
				}
				else if (val == 255) {
					blueTrueCount++;
				}
				blueTotal++;
			}
		}
		// 判断红色进度条
		for (int i = 0; i < mat_red.rows; i++) {
			for (int j = 0; j < mat_red.cols; j++) {
				int val = (int)mat_red.at<uchar>(i, j);
				if (val == 73) {
					redFalseCount++;
				}
				else if (val == 165 || val == 175) {
					redTrueCount++;
				}
				redTotal++;
			}
		}
		// 耐力进度条状态判断
		bool blueTrue = blueTrueCount == blueTotal, blueFalse = blueFalseCount == blueTotal;
		bool redTrue = redTrueCount == redTotal, redFalse = redFalseCount == redTotal;
		// 蓝色队列更新（判断是否需要收竿）
		if (cq_blue->isfull()) {
			cq_blue->dequeue();
		}
		if (blueFalse && redTrue) {
			cq_blue->enqueue(TRUE);
		}
		else {
			cq_blue->enqueue(FALSE);
		}
		// 红色队列更新（判断耐力条是否存在）
		if (cq_red->isfull()) {
			cq_red->dequeue();
		}
		if ((blueTrue || blueFalse) && (redTrue || redFalse)) {
			cq_red->enqueue(TRUE);
		}
		else {
			cq_red->enqueue(FALSE);
		}
		// 判断是否需要收竿
		int needFinishCount = 0;
		int blueSize = cq_blue->size();
		if (blueSize == params.cqBlueSize) {
			for (int i = cq_blue->m_frontIdx; i < cq_blue->m_frontIdx + cq_blue->size(); i++) {
				if (cq_blue->m_queueArr[i] == TRUE) {
					needFinishCount++;
				}
			}
			if (needFinishCount == blueSize) {
				params.needFinish = TRUE;
			}
		}
		else {
			params.needFinish = FALSE;
		}
		// 判断耐力条是否存在
		int existBarCount = 0;
		int redSize = cq_red->size();
		if (redSize == params.cqRedSize) {
			for (int i = cq_red->m_frontIdx; i < cq_red->m_frontIdx + cq_red->size(); i++) {
				if (cq_red->m_queueArr[i] == TRUE) {
					existBarCount++;
				}
			}
			if (existBarCount == redSize) {
				params.existBar = TRUE;
			}
		}
		else {
			params.existBar = FALSE;
		}
		if (debug) {
			//std::cout << "needFinishCount：" << needFinishCount << "，existBarCount：" << existBarCount << "，blueSize：" << blueSize << "，redSize：" << redSize << endl;
		}
		Sleep(100);
	}
}

// 模拟按下按键
void keyDown(HWND hwnd, BYTE bVk, int delay) {
	while (params.pause || params.systemPause) {
		Sleep(1000);
	}
	PostMessage(hwnd, WM_KEYDOWN, bVk, 0);
	Sleep(delay);
	PostMessage(hwnd, WM_KEYUP, bVk, 0);
}

// 模拟按下按键
void keyDownSend(HWND hwnd, BYTE bVk, int delay) {
	while (params.pause || params.systemPause) {
		Sleep(1000);
	}
	SendMessage(hwnd, WM_KEYDOWN, bVk, 0);
	Sleep(delay);
	SendMessage(hwnd, WM_KEYUP, bVk, 0);
}

// 收竿弹出页检测 TRUE=检测到
bool checkFinishPage(int testTimes) {
	// 等待收竿弹出页
	int maxTimes = testTimes, times = 0;
	while (true) {
		if (times >= maxTimes) {
			return FALSE;
		}
		bool debug = config.debug;
		Mat src = getSrc(params.rect_gb);
		if (isMatMatch(src, params.tpl_gb, 9, 0.19, debug) || isMatMatch(src, params.tpl_gb_new, 9, 0.19, debug)) {
			return TRUE;
		}
		times++;
		Sleep(1000);
	}
}

// 获取当前鼠标位置
POINT getCursorPos() {
	POINT p = { 0, 0 };
	GetCursorPos(&p);
	return p;
}

// 模拟鼠标点击
void click(g_point point) {
	POINT p = getCursorPos();

	SetCursorPos(point.x, point.y);

	INPUT input{};
	input.type = INPUT_MOUSE;
	input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
	input.mi.time = NULL;
	SendInput(1, &input, sizeof(INPUT));
	Sleep(40);
	input = {};
	input.type = INPUT_MOUSE;
	input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
	input.mi.time = NULL;
	SendInput(1, &input, sizeof(INPUT));

	SetCursorPos(p.x, p.y);
}

// 模拟鼠标点击
void click(g_point p, long delay, int count) {
	for (int i = 0; i < count; i++) {
		click(p);
		Sleep(delay);
	}
}

// 抛竿操作
void throwHandleThread(int tryCount) {
	// 抛竿
	//if (tryCount >= 1)
	keyDownSend(params.hwnd, config.throw_btn, 100);
	params.cq_red->clear();
	params.existBar = FALSE;
	std::cout << "抛竿" << endl;
	// 尝试次数
	tryCount++;
	// 抛竿动画，大概4~8秒
	Sleep(4000);
	// 检测次数
	int checkCount = 0;
	// 每隔1秒检测一次
	while (TRUE) {
		// 如果检测到耐力条，说明抛竿成功
		if (params.existBar) {
			//std::cout << "检测到耐力条，判定为抛竿成功" << endl;
			return;
		}
		// 如果多次未检测到耐力条，说明抛竿失败，继续抛竿
		if (checkCount > 15) {
			if (tryCount < 3) {
				std::cout << "检测耐力条超时，判定为抛竿失败，将再次尝试抛竿..." << endl;
				thread thThrowHandle(throwHandleThread, tryCount);
				thThrowHandle.detach();
				return;
			}
			else {
				std::cout << "已尝试抛竿失败" << tryCount << "次，请截图控制台+游戏窗口反馈bug" << endl;
				exit();
			}	
		}
		checkCount++;
		Sleep(1000);
	}
}

// 收竿 ESC 抛竿
void finishHandle() {
	HWND hwnd = params.hwnd;
	bool debug = config.debug;
	// 收竿前摇延迟
	Sleep(config.delays_finish_before);
	// 停止钓鱼
	keyStop();
	// 收竿
	keyDownSend(params.hwnd, config.throw_btn, 100);
	params.cq_red->clear();
	params.existBar = FALSE;
	// 延迟1秒
	Sleep(config.delays_esc_before);
	// 检测收竿弹出页是否已打开
	if (checkFinishPage(9)) {
		if (debug) {
			cout << "已检测到收竿弹出页，将自动为您关闭弹出页，之后继续抛竿" << endl;
		}
		// ESC
		keyDownSend(hwnd, VK_ESCAPE, 100);
		// 延迟2秒
		Sleep(config.delays_esc_after);
		// 检测收竿弹出页是否已关闭
		while (checkFinishPage(1)) {
			// ESC
			keyDownSend(hwnd, VK_ESCAPE, 100);
			// 延迟1秒
			Sleep(config.delays_esc_after);
		}
		// 抛竿
		thread thThrowHandle(throwHandleThread, 0);
		thThrowHandle.detach();
	}
	else {
		if (debug || TRUE) {
			Mat gb = getSrc(params.rect_gb);
			imwrite("gb.bmp", gb);
			isMatMatch(gb, params.tpl_gb, 9, 0.19, TRUE);
			isMatMatch(gb, params.tpl_gb_new, 9, 0.19, TRUE);
			cout << "检测收竿弹出页超时，建议截图控制台+游戏窗口反馈bug" << endl;
			exit();
		}
	}
}

// 自动钓鱼
void autoFish() {
	if (params.needFinish) {
		std::cout << "收竿*" << ++params.fishCount << endl;
		if (config.throw_method == 1) {
			finishHandle();
		} 
		else if (config.throw_method == 2) {
			// 收竿
			click(params.point_fish, 50, 1);
			// 延迟delays_esc_before
			Sleep(config.delays_esc_before);
			// 关闭弹出页
			click(params.point_fish, 50, 1);
			// 延迟delays_esc_after
			Sleep(config.delays_esc_after);
			// 抛竿
			click(params.point_fish, 50, 1);
			// 抛竿动画，大概4~8秒
			Sleep(4000);
		}
		params.cq_blue->clear();
		params.needFinish = FALSE;
	}
}

// 窗口区域初始化
void initRect() {
	// 获取窗口句柄
	HWND hwnd = params.hwnd;
	//SetForegroundWindow(hwnd); //窗口置前
	RECT rect;
	// 获取客户区窗口坐标
	GetClientRect(hwnd, &rect);
	int w = rect.right - rect.left, h = rect.bottom - rect.top;
	if (w <= 1 || h <= 1 || w > 9999 || h > 9999) {
		std::cout << endl << "请先进入游戏！" << endl;
		exit();
	}
	// 客户区坐标转屏幕坐标
	POINT p1 = { rect.left, rect.top };
	POINT p2 = { rect.right, rect.bottom };
	ClientToScreen(hwnd, &p1);
	ClientToScreen(hwnd, &p2);
	rect.left = p1.x, rect.top = p1.y, rect.right = p2.x, rect.bottom = p2.y;
	// 获取上一次捕获的窗口坐标
	RECT r0 = params.rect;
	if (rect.left == r0.left && rect.right == r0.right && rect.top == r0.top && rect.bottom == r0.bottom) {
		return;
	}
	// 如果新坐标和上一次的不同，就校验分辨率大小，自动调整为1280*720
	params.rect = rect;
	params.width = w, params.height = h;
	// 窗口分辨率校验
	std::cout << "提示：捕获到窗口" << w << "*" << h;
	if (w != 1280 || h != 720) {
		std::cout << "，自动为您调整为1280*720";
		// 计算边框大小
		RECT windowsRect;
		GetWindowRect(hwnd, &windowsRect);
		int dx = (windowsRect.right - windowsRect.left) - (rect.right - rect.left);
		int dy = (windowsRect.bottom - windowsRect.top) - (rect.bottom - rect.top);
		// 计算新窗体位置
		int newWidth = 1280 + dx, newHeight = 720 + dy;
		int newLeft = (rect.left + rect.right) / 2 - newWidth / 2;
		int newTop = (rect.top + rect.bottom) / 2 - newHeight / 2;
		// 移动至新窗体位置
		MoveWindow(hwnd, newLeft, newTop, newWidth, newHeight, TRUE);
		// 重新读取窗体
		cout << endl;
		initRect();
	}
	std::cout << endl;

	// 获取目标区域、模板图片
	RECT rect_center = getCenterRect();	//体力条区域
	RECT rect_blue = getBlueRect(); // 蓝色进度条区域
	RECT rect_red = getRedRect(); // 红色进度条区域
	RECT rect_gb = getGbRect(); // 关闭进度条区域
	int h_center = rect_center.bottom - rect_center.top;
	Mat tpl_center = getTpl("template.png", 5 * h_center, h_center); //黄条模版
	Mat tpl_point = getTpl("tpl.png", h_center / 3, h_center); //白点模版
	params.rect_center = rect_center, params.rect_blue = rect_blue, params.rect_red = rect_red, params.rect_gb = rect_gb;
	params.tpl_center = tpl_center, params.tpl_point = tpl_point;
	// 定位收竿按钮区域
	if (config.throw_method == 2) {
		POINT point_fish = getFishPoint();
		params.point_fish.x = point_fish.x;
		params.point_fish.y = point_fish.y;
	}
	// 重置移动状态
	keyReset();
}

// 窗口区域初始化 - 多线程
void initRectThread() {
	Sleep(2000);
	while (true) {
		while (params.pause || params.systemPause) {
			Sleep(1000);
		}
		initRect();
		Sleep(1000);
	}
}

// 程序初始化
void init() {
	// 脚本信息
	SetConsoleTitle(L"幻塔-自动钓鱼 v2.6.6");

	// 提示信息
	std::cout << "    幻塔-自动钓鱼 v2.6.6  --by gosick39（幻塔-学习交流Q群：565943273）" << endl << endl;
	std::cout << "  注意：本程序仅学习使用，禁止商用，请于24小时内自行删除！" << endl << endl;
	std::cout << "  使用方法：抛竿后，双击打开脚本 ht-fish.exe（详见使用说明.txt）" << endl << endl;

	// 加载配置文件
	loadConfig();

	// 获取窗口句柄
	HWND hwnd = FindWindowEx(nullptr, nullptr, L"UnrealWindow", nullptr);
	HDC hdc = GetDC(hwnd);  // 获取窗口的设备上下文
	int dpi = GetDpiForWindow(hwnd);  // 获取窗口的 DPI 缩放比例
	ScaleViewportExtEx(hdc, dpi, dpi, dpi / 96, dpi / 96, nullptr);  // 缩放视窗区域
	ScaleWindowExtEx(hdc, dpi, dpi, dpi / 96, dpi / 96, nullptr);  // 缩放窗口区域
	params.hwnd = hwnd;

	// 窗口区域初始化
	initRect();

	// 动态识别窗口位置
	thread thInitRect(initRectThread);
	thInitRect.detach();

	// 改变脚本位置
	RECT r = params.rect;
	MoveWindow(GetConsoleWindow(), r.left, (r.top + r.bottom) / 2, (r.right - r.left) / 2, (r.bottom - r.top) / 2, TRUE);

	// 一次性加载的模板
	params.tpl_gb = getTpl("gb.bmp");
	params.tpl_gb_new = getTpl("gb_new.bmp");

	// 初始化参数
	int cqBlueSize = 12;
	int cqRedSize = 12;
	params.cq_blue = new Ciclequeue(cqBlueSize);
	params.cq_red = new Ciclequeue(cqRedSize);
	params.cqBlueSize = cqBlueSize;
	params.cqRedSize = cqRedSize;
	params.fishCount = 0;
}

void fish() {
	int key = 0;
	while (key != 27)
	{
		// 暂停判断
		while (params.pause || params.systemPause) {
			keyStop();
			Sleep(1000);
		}
		// 自动钓鱼操作
		autoFish();
		// 读取目标区域及模板
		RECT r = params.rect_center;
		Mat templ = params.tpl_center; //黄条模版
		Mat tpl = params.tpl_point; //白点模版
		// 截取目标区域
		Mat src = getSrc(r);
		if (config.debug_pic) {
			imwrite("print_center.jpg", src);
		}
		// 模板匹配获取黄条位置
		g_point a1 = MatchingMethod(src, templ);
		if (config.debug_pic) {
			imwrite("print_templ.jpg", a1.match);
		}
		if (!matchYellow(a1.match)) {
			keyStop();
			waitKey(config.delays);
			continue;
		}
		// 模板匹配获取白点位置
		g_point a2 = MatchingMethod(src, tpl);
		if (config.debug_pic) {
			imwrite("print_tpl.jpg", a2.match);
		}
		// 根据黄条、白点位置发出键盘信号
		if (config.is_log) std::cout << a1 << " || " << a2 << endl;
		if (a1.x != 0 && a1.y != 0 && a2.x != 0 && a2.y != 0) {
			int yd = a1.y - a2.y;
			int xd = a1.x - a2.x;
			if (abs(yd) <= 1) {
				if (xd < -3) {
					if (config.is_log) std::cout << "向左走" << endl;
					keyLeft();
				}
				else if (xd < -2) {
					if (config.is_log) std::cout << "向左走小步" << endl;
					keyLeftS();
				}
				else if (xd > 3) {
					if (config.is_log) std::cout << "向右走" << endl;
					keyRight();
				}
				else if (xd > 2) {
					if (config.is_log) std::cout << "向右走小步" << endl;
					keyRightS();
				}
				else {
					if (config.is_log) std::cout << "停下" << endl;
					keyStop();
				}
			}
		}
		key = waitKey(config.delays);
	}
}

int main() {

	init();
	std::cout << endl;

	// 开启自动拉杆
	if (config.is_auto) {
		// 动态读取进度条状态
		thread thReadStatus(readStatusThread);
		thReadStatus.detach();
	}

	// 如果开启暂停功能
	if (config.is_pause) {
		std::cout << "按下Tab键可暂停/继续" << endl;
		thread th(fish);
		th.detach();
		while (1) {
			if (KEY_PRESSED(VK_TAB)) {
				if (params.pause) {
					params.pause = false;
					std::cout << "已继续" << endl;
				}
				else {
					params.pause = true;
					std::cout << "已暂停" << endl;
				}
			}
			Sleep(500);
		}
	}
	else {
		fish();
	}
	return 0;
}